#!/usr/bin/env node

import fs from "node:fs";
import path from "node:path";
import { config as loadEnv } from "dotenv";
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
import yaml from "js-yaml";
import { FigmaService, type FigmaAuthOptions } from "./services/figma.js";
import { getFigmaDataTool } from "./mcp/tools/get-figma-data-tool.js";
import { createMinifiedDesign, type ExtractedDesign } from "./transformers/minify.js";

type SupportedFormats = "yaml" | "json";

function parseFigmaUrl(figmaUrl: string): { fileKey?: string; nodeId?: string } {
  try {
    const parsed = new URL(figmaUrl);
    const pathSegments = parsed.pathname.split("/").filter(Boolean);

    if (pathSegments.length === 0) {
      return {};
    }

    const prefixes = new Set(["file", "design", "proto", "presentation"]);
    const fileKey =
      pathSegments.length >= 2 && prefixes.has(pathSegments[0])
        ? pathSegments[1]
        : pathSegments[0];

    const rawNodeId = parsed.searchParams.get("node-id") ?? parsed.searchParams.get("nodeId");

    return {
      fileKey: fileKey || undefined,
      nodeId: rawNodeId ? decodeURIComponent(rawNodeId) : undefined,
    };
  } catch {
    return {};
  }
}

function resolveOutputFormat(
  cliFormat: SupportedFormats | undefined,
  envFormat: string | undefined,
): SupportedFormats {
  if (cliFormat) {
    return cliFormat;
  }

  if (envFormat === "json" || envFormat === "yaml") {
    return envFormat;
  }

  return "yaml";
}

async function main() {
  loadEnv({ path: path.resolve(process.cwd(), ".env"), override: false });

  const argv = yargs(hideBin(process.argv))
    .scriptName("figma-developer-mcp-fetch")
    .usage(
      "$0 --figma-api-key <token> --url <figma-url> --output-file <path>\n" +
        "或 $0 --figma-api-key <token> --file-key <key> [--node-id <id>] [--depth <n>] [--output-file <path>]",
    )
    .options({
      url: {
        type: "string",
        describe: "Figma 文件或设计的 URL，将自动解析 fileKey 与 nodeId",
      },
      "file-key": {
        type: "string",
        describe: "Figma 文件的 fileKey",
      },
      "node-id": {
        type: "string",
        describe: "要提取的节点 ID（例如 52-69692 或 52:69692）",
      },
      depth: {
        type: "number",
        describe: "可选，控制遍历层级深度限制",
      },
      "figma-api-key": {
        type: "string",
        describe: "Figma 个人访问令牌，未提供时会读取 FIGMA_API_KEY",
      },
      "figma-oauth-token": {
        type: "string",
        describe: "Figma OAuth Bearer Token，未提供时会读取 FIGMA_OAUTH_TOKEN",
      },
      "output-format": {
        type: "string",
        choices: ["yaml", "json"] as const,
        describe: "输出格式",
      },
      "output-file": {
        type: "string",
        describe: "要保存结果的文件路径，不填则打印到标准输出",
      },
      "min-output-file": {
        type: "string",
        describe: "可选，自定义精简版本的输出路径，默认基于 output-file 或 fileKey 自动生成",
      },
      "keep-metadata": {
        type: "boolean",
        default: true,
        describe: "默认保留 metadata，若需移除可使用 --no-keep-metadata",
      },
    })
    .help()
    .strict()
    .parseSync();

  const parsedFromUrl = argv.url ? parseFigmaUrl(argv.url) : {};

  const envFileKey = process.env.FIGMA_FILE_KEY;
  const envNodeId = process.env.FIGMA_NODE_ID;

  const fileKey = (argv["file-key"] ?? parsedFromUrl.fileKey ?? envFileKey) || undefined;
  const nodeId = (argv["node-id"] ?? parsedFromUrl.nodeId ?? envNodeId) || undefined;
  const depth = argv.depth;

  if (!fileKey) {
    console.error("缺少 fileKey，请通过 --file-key、--url 或 FIGMA_FILE_KEY 环境变量提供。");
    process.exit(1);
  }

  const figmaApiKey = argv["figma-api-key"] ?? process.env.FIGMA_API_KEY;
  const figmaOAuthToken = argv["figma-oauth-token"] ?? process.env.FIGMA_OAUTH_TOKEN;

  const authOptions: FigmaAuthOptions = {
    figmaApiKey: figmaApiKey ?? "",
    figmaOAuthToken: figmaOAuthToken ?? "",
    useOAuth: Boolean(figmaOAuthToken ?? false),
  };

  if (!authOptions.useOAuth && !authOptions.figmaApiKey) {
    console.error("需要提供 Figma API Key 或 OAuth Token。");
    process.exit(1);
  }

  const outputFormat = resolveOutputFormat(
    argv["output-format"] as SupportedFormats | undefined,
    process.env.OUTPUT_FORMAT,
  );

  try {
    const figmaService = new FigmaService(authOptions);
    const result = await getFigmaDataTool.handler(
      { fileKey, nodeId: nodeId || undefined, depth },
      figmaService,
      outputFormat,
    );

    if (result.isError) {
      const message = result.content[0]?.text ?? "未知错误";
      console.error(message);
      process.exit(1);
    }

    const text = result.content[0]?.text ?? "";
    const keepMetadata = Boolean(argv["keep-metadata"]);

    let structuredData: unknown;
    try {
      structuredData = outputFormat === "json" ? JSON.parse(text) : yaml.load(text);
    } catch (parseError) {
      const reason = parseError instanceof Error ? parseError.message : String(parseError);
      console.error(`解析输出以构建精简版本时失败：${reason}`);
      process.exit(1);
    }

    if (!structuredData || typeof structuredData !== "object") {
      console.error("输出数据格式异常，无法生成精简版本。");
      process.exit(1);
    }

    const minifiedData = createMinifiedDesign(structuredData as ExtractedDesign, {
      keepMetadata,
      preserveNodeAnchors: true,
    });
    const minifiedText =
      outputFormat === "json"
        ? JSON.stringify(minifiedData, null, 2)
        : yaml.dump(minifiedData);

    const resolvedOutputFile = argv["output-file"] ? path.resolve(argv["output-file"]) : undefined;
    const minOutputPath = resolveMinOutputPath(
      argv["min-output-file"],
      resolvedOutputFile,
      outputFormat,
      fileKey,
    );

    if (resolvedOutputFile && path.resolve(minOutputPath) === resolvedOutputFile) {
      console.error("精简输出路径不能与原始输出路径相同，请使用 --min-output-file 指定不同文件。");
      process.exit(1);
    }

    if (resolvedOutputFile) {
      ensureDirectoryForFile(resolvedOutputFile);
      fs.writeFileSync(resolvedOutputFile, text, "utf8");
      console.log(`已写入到 ${resolvedOutputFile}`);
    } else {
      process.stdout.write(text);
      if (!text.endsWith("\n")) {
        process.stdout.write("\n");
      }
    }

    ensureDirectoryForFile(minOutputPath);
    fs.writeFileSync(minOutputPath, minifiedText, "utf8");
    console.log(`已写入精简版本到 ${minOutputPath}`);
  } catch (error) {
    const message = error instanceof Error ? error.message : String(error);
    console.error(`获取 Figma 数据失败：${message}`);
    process.exit(1);
  }
}

void main();

function resolveMinOutputPath(
  explicitPath: string | undefined,
  fullOutputPath: string | undefined,
  format: SupportedFormats,
  fileKey: string,
): string {
  if (explicitPath) {
    return path.resolve(explicitPath);
  }

  if (fullOutputPath) {
    const parsed = path.parse(fullOutputPath);
    const extension = parsed.ext || getDefaultExtension(format);
    return path.join(parsed.dir, `${parsed.name}.min${extension}`);
  }

  const defaultName = `figma-${fileKey}.min${getDefaultExtension(format)}`;
  return path.resolve(process.cwd(), defaultName);
}

function getDefaultExtension(format: SupportedFormats): string {
  return format === "json" ? ".json" : ".yaml";
}

function ensureDirectoryForFile(targetPath: string): void {
  const directory = path.dirname(targetPath);
  if (!fs.existsSync(directory)) {
    fs.mkdirSync(directory, { recursive: true });
  }
}
